package com.song.tools.core.util;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;

/**
 * 对象工具类
 *
 * @author song tools
 * @since 2024-06-26
 */
public class ObjectUtils {

    /**
     * 检查给定对象是否为空。
     * <p>
     * 本方法提供了一种通用的方式来判断一个对象是否为空。它不仅考虑了对象为null的情况，
     * 还考虑了对象不为null但其内部状态为空的情况。这通过使用TypeHandler来处理特定类型的空检查。
     *
     * @param obj 要检查的对象。可以是任何类型的对象。
     * @return 如果对象为空，则返回true；否则返回false。
     */
    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }

        TypeHandler handler = getTypeHandler(obj);
        return handler.isEmpty(obj);
    }

    /**
     * 检查对象是否不为空。
     * <p>
     * 该方法通过调用 {@link #isEmpty(Object)} 方法的非空检查来确定对象是否不为空。
     * 主要是为了提供一种更直观的方法来判断对象是否不为空，而不是直接使用逻辑否定。
     *
     * @param obj 要检查的对象
     * @return 如果对象不为空，则返回 true；否则返回 false。
     */
    public static boolean isNotEmpty(Object obj) {
        return !isEmpty(obj);
    }

    private static TypeHandler getTypeHandler(Object obj) {
        if (obj instanceof Optional) {
            return new OptionalHandler();
        } else if (obj instanceof CharSequence) {
            return new CharSequenceHandler();
        } else if (obj.getClass().isArray()) {
            return new ArrayHandler();
        } else if (obj instanceof Collection) {
            return new CollectionHandler();
        } else if (obj instanceof Map) {
            return new MapHandler();
        } else {
            return new DefaultHandler();
        }
    }


    interface TypeHandler {
        boolean isEmpty(Object obj);
    }


    static class OptionalHandler implements TypeHandler {
        public boolean isEmpty(Object obj) {
            return ((Optional<?>) obj).isEmpty();
        }
    }

    static class CharSequenceHandler implements TypeHandler {
        public boolean isEmpty(Object obj) {
            return ((CharSequence) obj).isEmpty();
        }
    }

    static class ArrayHandler implements TypeHandler {
        public boolean isEmpty(Object obj) {
            return Array.getLength(obj) == 0;
        }
    }

    static class CollectionHandler implements TypeHandler {
        public boolean isEmpty(Object obj) {
            return ((Collection<?>) obj).isEmpty();
        }
    }

    static class MapHandler implements TypeHandler {
        public boolean isEmpty(Object obj) {
            return ((Map<?, ?>) obj).isEmpty();
        }
    }

    static class DefaultHandler implements TypeHandler {
        public boolean isEmpty(Object obj) {
            return false;
        }
    }
}
